`include "defines.v"
`include "inst.v"
module iduHasC(
  input                clk ,
  input                rst_n,
  input [`VADDR_W-1:0] boot_addr,
  input                ctrl_idu_flush_i,
  input [`VADDR_W-1:0] redict_idu_pc_i,
  output               idu_ctrl_stall_o,
  // frontend in 
  input  [7:0]  ibf_idu_valid_i,
  output [2:0]  idu_ibf_ready_o,
  input  [15:0] ibf_idu_instIn0_i ,
  input  [15:0] ibf_idu_instIn1_i ,
  input  [15:0] ibf_idu_instIn2_i ,
  input  [15:0] ibf_idu_instIn3_i ,
  input  [15:0] ibf_idu_instIn4_i ,
  input  [15:0] ibf_idu_instIn5_i ,
  input  [15:0] ibf_idu_instIn6_i ,
  input  [15:0] ibf_idu_instIn7_i ,
  // IDU 输出的寄存器信号
  output                  idu_isu_valid_o   ,
  input                   isu_idu_ready_i   ,
  output [`FU_W-1:0]      idu_isu_fu_o      ,
  output [`OP_W-1:0]      idu_isu_op_o      ,
  output [4:0]            idu_isu_rs1_o     ,
  output [4:0]            idu_isu_rs2_o     ,
  output [4:0]            idu_isu_rd_o      ,
  output                  idu_isu_rfwen_o   ,
  output [1:0]            idu_isu_src1_o    ,
  output [1:0]            idu_isu_src2_o    ,
  output [`XLEN-1:0]      idu_isu_imm_o     ,
  output [`VADDR_W-1:0]   idu_isu_pc_o      ,
  output [31:0]           idu_isu_inst_o    ,
  output                  idu_isu_isCps_o   ,
  output [`BPU_PRE_W-1:0] idu_isu_predict_o 
);
reg  [`VADDR_W-1:0] iduPc;

wire [31:0] curInst         = {ibf_idu_instIn1_i,ibf_idu_instIn0_i}; 
wire        outSel          = (curInst[1:0] != 2'b11); // 1 is compress inst 
assign      idu_ibf_ready_o = {2{isu_idu_ready_i}} & (({2{(outSel & ibf_idu_valid_i[0])}} & 2'd1) | ({2{(~outSel & (&ibf_idu_valid_i[1:0]))}} & 2'd2) );
reg         needStop  ;
reg         stall     ;
assign      idu_isu_valid_o = outSel ? ibf_idu_valid_i[0] : (ibf_idu_valid_i[0] & ibf_idu_valid_i[1]);
wire        idu_isu_hs      = isu_idu_ready_i && idu_isu_valid_o ;
always@(posedge clk or negedge rst_n)
  if(~rst_n)
    stall <= 'd0;
  else if (ctrl_idu_flush_i)
    stall <= 'd0;
  else if (idu_isu_hs && needStop)
    stall <= 'd1;

// normal decoder  0
wire [31:0] inst   = curInst;
wire [ 6:0] opcode = inst[ 6: 0];
wire [ 4:0] rd     = inst[11: 7];
wire [ 2:0] func3  = inst[14:12];
wire [ 4:0] rs1    = inst[19:15];
wire [ 4:0] rs2    = inst[24:20];
wire [11:0] imm    = inst[31:20];
/* imm generate */
wire [`XLEN-1:0] imm_I = {{52{inst[31]}},inst[31:20]};
wire [`XLEN-1:0] imm_S = {{52{inst[31]}},inst[31:25],inst[11:7]};
wire [`XLEN-1:0] imm_B = {{52{inst[31]}},inst[7],inst[30:25],inst[11:8],1'b0};
wire [`XLEN-1:0] imm_U = {{32{inst[31]}},inst[31:12],12'd0};
wire [`XLEN-1:0] imm_J = {{44{inst[31]}},inst[19:12],inst[20],inst[30:21],1'b0};
wire [`XLEN-1:0] imm_R = {{59{inst[31]}},inst[19:15]};
/* singel inst decoder */
reg [16:0] decsignal ;
always@(*)begin
  casez(inst)
    //                          v1  immtype3   fu4       op4         r1rf2    r2rf2   wrf1
    `SLL   :begin decsignal = {`Y , `IMM_X , `FU_ALU , `ALU_SLL  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `ADD   :begin decsignal = {`Y , `IMM_X , `FU_ALU , `ALU_ADD  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `SUB   :begin decsignal = {`Y , `IMM_X , `FU_ALU , `ALU_SUB  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `SLT   :begin decsignal = {`Y , `IMM_X , `FU_ALU , `ALU_SLT  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `SLTU  :begin decsignal = {`Y , `IMM_X , `FU_ALU , `ALU_SLTU , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `AND   :begin decsignal = {`Y , `IMM_X , `FU_ALU , `ALU_AND  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `OR    :begin decsignal = {`Y , `IMM_X , `FU_ALU , `ALU_OR   , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `XOR   :begin decsignal = {`Y , `IMM_X , `FU_ALU , `ALU_XOR  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `SRA   :begin decsignal = {`Y , `IMM_X , `FU_ALU , `ALU_SRA  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `SRL   :begin decsignal = {`Y , `IMM_X , `FU_ALU , `ALU_SRL  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end

    `ADDI  :begin decsignal = {`Y , `IMM_I , `FU_ALU , `ALU_ADD  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `ANDI  :begin decsignal = {`Y , `IMM_I , `FU_ALU , `ALU_AND  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `ORI   :begin decsignal = {`Y , `IMM_I , `FU_ALU , `ALU_OR   , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `XORI  :begin decsignal = {`Y , `IMM_I , `FU_ALU , `ALU_XOR  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `SLTI  :begin decsignal = {`Y , `IMM_I , `FU_ALU , `ALU_SLT  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `SLTIU :begin decsignal = {`Y , `IMM_I , `FU_ALU , `ALU_SLTU , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `SLLI  :begin decsignal = {`Y , `IMM_I , `FU_ALU , `ALU_SLL  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `SRAI  :begin decsignal = {`Y , `IMM_I , `FU_ALU , `ALU_SRA  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `SRLI  :begin decsignal = {`Y , `IMM_I , `FU_ALU , `ALU_SRL  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end

    `ADDIW :begin decsignal = {`Y , `IMM_I , `FU_ALUW, `ALU_ADD  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `SLLIW :begin decsignal = {`Y , `IMM_I , `FU_ALUW, `ALU_SLL  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `SRLIW :begin decsignal = {`Y , `IMM_I , `FU_ALUW, `ALU_SRL  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `SRAIW :begin decsignal = {`Y , `IMM_I , `FU_ALUW, `ALU_SRA  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `ADDW  :begin decsignal = {`Y , `IMM_X , `FU_ALUW, `ALU_ADD  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `SUBW  :begin decsignal = {`Y , `IMM_X , `FU_ALUW, `ALU_SUB  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `SLLW  :begin decsignal = {`Y , `IMM_X , `FU_ALUW, `ALU_SLL  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `SRLW  :begin decsignal = {`Y , `IMM_X , `FU_ALUW, `ALU_SRL  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `SRAW  :begin decsignal = {`Y , `IMM_X , `FU_ALUW, `ALU_SRA  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end

    `MUL   :begin decsignal = {`Y , `IMM_X , `FU_MDU , `MDU_MUL    , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `MULH  :begin decsignal = {`Y , `IMM_X , `FU_MDU , `MDU_MULH   , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `MULHSU:begin decsignal = {`Y , `IMM_X , `FU_MDU , `MDU_MULHSU , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `MULHU :begin decsignal = {`Y , `IMM_X , `FU_MDU , `MDU_MULHU  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `DIV   :begin decsignal = {`Y , `IMM_X , `FU_MDU , `MDU_DIV    , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `DIVU  :begin decsignal = {`Y , `IMM_X , `FU_MDU , `MDU_DIVU   , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `REM   :begin decsignal = {`Y , `IMM_X , `FU_MDU , `MDU_REM    , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `REMU  :begin decsignal = {`Y , `IMM_X , `FU_MDU , `MDU_REMU   , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `MULW  :begin decsignal = {`Y , `IMM_X , `FU_MDU , `MDU_MULW   , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `DIVW  :begin decsignal = {`Y , `IMM_X , `FU_MDU , `MDU_DIVW   , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `DIVUW :begin decsignal = {`Y , `IMM_X , `FU_MDU , `MDU_DIVUW  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `REMW  :begin decsignal = {`Y , `IMM_X , `FU_MDU , `MDU_REMW   , `SRC_RF , `SRC_RF , `Y };needStop=`N;end
    `REMUW :begin decsignal = {`Y , `IMM_X , `FU_MDU , `MDU_REMUW  , `SRC_RF , `SRC_RF , `Y };needStop=`N;end

    `JAL   :begin decsignal = {`Y , `IMM_J , `FU_BRU , `BRU_JAL  , `SRC_PC , `SRC_IM , `Y };needStop=`N;end
    `JALR  :begin decsignal = {`Y , `IMM_I , `FU_BRU , `BRU_JALR , `SRC_RF , `SRC_XX , `Y };needStop=`N;end
    `BEQ   :begin decsignal = {`Y , `IMM_B , `FU_BRU , `BRU_BEQ  , `SRC_RF , `SRC_RF , `N };needStop=`N;end
    `BNE   :begin decsignal = {`Y , `IMM_B , `FU_BRU , `BRU_BNE  , `SRC_RF , `SRC_RF , `N };needStop=`N;end
    `BGE   :begin decsignal = {`Y , `IMM_B , `FU_BRU , `BRU_BGE  , `SRC_RF , `SRC_RF , `N };needStop=`N;end
    `BGEU  :begin decsignal = {`Y , `IMM_B , `FU_BRU , `BRU_BGEU , `SRC_RF , `SRC_RF , `N };needStop=`N;end
    `BLT   :begin decsignal = {`Y , `IMM_B , `FU_BRU , `BRU_BLT  , `SRC_RF , `SRC_RF , `N };needStop=`N;end
    `BLTU  :begin decsignal = {`Y , `IMM_B , `FU_BRU , `BRU_BLTU , `SRC_RF , `SRC_RF , `N };needStop=`N;end
    
    `LB    :begin decsignal = {`Y , `IMM_I , `FU_LSU , `LSU_RBS  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `LBU   :begin decsignal = {`Y , `IMM_I , `FU_LSU , `LSU_RBU  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `LH    :begin decsignal = {`Y , `IMM_I , `FU_LSU , `LSU_RHS  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `LHU   :begin decsignal = {`Y , `IMM_I , `FU_LSU , `LSU_RHU  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `LW    :begin decsignal = {`Y , `IMM_I , `FU_LSU , `LSU_RWS  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `LWU   :begin decsignal = {`Y , `IMM_I , `FU_LSU , `LSU_RWU  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `LD    :begin decsignal = {`Y , `IMM_I , `FU_LSU , `LSU_RDX  , `SRC_RF , `SRC_IM , `Y };needStop=`N;end
    `SB    :begin decsignal = {`Y , `IMM_S , `FU_LSU , `LSU_WBX  , `SRC_RF , `SRC_RF , `N };needStop=`N;end
    `SH    :begin decsignal = {`Y , `IMM_S , `FU_LSU , `LSU_WHX  , `SRC_RF , `SRC_RF , `N };needStop=`N;end
    `SW    :begin decsignal = {`Y , `IMM_S , `FU_LSU , `LSU_WWX  , `SRC_RF , `SRC_RF , `N };needStop=`N;end
    `SD    :begin decsignal = {`Y , `IMM_S , `FU_LSU , `LSU_WDX  , `SRC_RF , `SRC_RF , `N };needStop=`N;end

    `AUIPC :begin decsignal = {`Y , `IMM_U , `FU_ALU , `ALU_ADD  , `SRC_PC , `SRC_IM , `Y };needStop=`N;end
    `LUI   :begin decsignal = {`Y , `IMM_U , `FU_ALU , `ALU_ADD  , `SRC_XX , `SRC_IM , `Y };needStop=`N;end

    `CSRRW :begin decsignal = {`Y , `IMM_X , `FU_CSR , `CSR_W    , `SRC_RF , `SRC_XX , `Y }; needStop=`Y;end
    `CSRRS :begin decsignal = {`Y , `IMM_X , `FU_CSR , `CSR_S    , `SRC_RF , `SRC_XX , `Y }; needStop=|rs1;end
    `CSRRC :begin decsignal = {`Y , `IMM_X , `FU_CSR , `CSR_C    , `SRC_RF , `SRC_XX , `Y }; needStop=`Y;end
    `CSRRWI:begin decsignal = {`Y , `IMM_R , `FU_CSR , `CSR_W    , `SRC_XX , `SRC_IM , `Y }; needStop=`Y;end
    `CSRRSI:begin decsignal = {`Y , `IMM_R , `FU_CSR , `CSR_S    , `SRC_XX , `SRC_IM , `Y }; needStop=`Y;end
    `CSRRCI:begin decsignal = {`Y , `IMM_R , `FU_CSR , `CSR_C    , `SRC_XX , `SRC_IM , `Y }; needStop=`Y;end

    `ECALL :begin decsignal = {`Y , `IMM_X , `FU_CSR , `CSR_P    , `SRC_XX , `SRC_XX , `N }; needStop=`Y;end
    `MRET  :begin decsignal = {`Y , `IMM_X , `FU_CSR , `CSR_P    , `SRC_XX , `SRC_XX , `N }; needStop=`Y;end

    `FENCE_I:begin decsignal = {`Y , `IMM_X , `FU_LSU , `LSU_FEI  , `SRC_XX , `SRC_XX , `N }; needStop=`Y;end

    `TRAP  :begin decsignal = {`Y , `IMM_X , `FU_ALU , `ALU_ADD  , `SRC_XX , `SRC_XX , `N }; needStop=`Y;end
    `PUTCH :begin decsignal = {`Y , `IMM_X , `FU_ALU , `ALU_ADD  , `SRC_XX , `SRC_XX , `N }; needStop=`N;end
    `EBREAK:begin decsignal = {`Y , `IMM_X , `FU_ALU , `ALU_ADD  , `SRC_XX , `SRC_XX , `N }; needStop=`N;end
    
    // `NOP   :decsignal = {`Y , `IMM_X , `FU_ALU , `ALU_ADD  , `SRC_XX , `SRC_XX , `N };needStop=`N;
  default: begin decsignal = {`N , `IMM_X , `FU_XXX , `ALU_XXXX , `N,   `N ,  `N};needStop=`N;end
  endcase
end

wire [15:0] cinst   = curInst[15: 0];
wire [1:0]  cop2    = curInst[1 : 0];
wire [ 4:0] Crd     = curInst[11: 7];
wire [ 2:0] cfunc3  = curInst[15:13];
wire [ 4:0] Crs1    = curInst[11: 7];
wire [ 4:0] Crs2    = curInst[6 : 2];
reg [4:0]        crs1;
reg [4:0]        crs2;
reg [4:0]        crd ;
reg [1:0]        csrc1;
reg [1:0]        csrc2;
reg              cValid;
reg  [`FU_W-1:0] cfu ;
reg  [`OP_W-1:0] cop ;
reg              cwen;
reg  [`XLEN-1:0] cimm;

// fu & op
always@(*)begin
  casez(cinst)
  
    `CBEQZ     :begin cfu=`FU_BRU ; cop=`BRU_BEQ  ; cwen=`N;end
    `CBNEZ     :begin cfu=`FU_BRU ; cop=`BRU_BNE  ; cwen=`N;end
    `CJ        :begin cfu=`FU_BRU ; cop=`BRU_JAL  ; cwen=`N;end
    `CJR       :begin cfu=`FU_BRU ; cop=`BRU_JALR ; cwen=`N;end
    `CJALR     :begin cfu=`FU_BRU ; cop=`BRU_CJALR; cwen=`Y;end

    `CADD      :begin cfu=`FU_ALU ; cop=`ALU_ADD; cwen=`Y;end
    `CADDI     :begin cfu=`FU_ALU ; cop=`ALU_ADD; cwen=`Y;end
    `CADDI16SP :begin cfu=`FU_ALU ; cop=`ALU_ADD; cwen=`Y;end
    `CADDI4SPN :begin cfu=`FU_ALU ; cop=`ALU_ADD; cwen=`Y;end
    `CADDIW    :begin cfu=`FU_ALUW; cop=`ALU_ADD; cwen=`Y;end
    `CADDW     :begin cfu=`FU_ALUW; cop=`ALU_ADD; cwen=`Y;end
    `CAND      :begin cfu=`FU_ALU ; cop=`ALU_AND; cwen=`Y;end
    `CANDI     :begin cfu=`FU_ALU ; cop=`ALU_AND; cwen=`Y;end
    `CLI       :begin cfu=`FU_ALU ; cop=`ALU_ADD; cwen=`Y;end
    `CLUI      :begin cfu=`FU_ALU ; cop=`ALU_ADD; cwen=`Y;end  
    `CMV       :begin cfu=`FU_ALU ; cop=`ALU_ADD; cwen=`Y;end
    `COR       :begin cfu=`FU_ALU ; cop=`ALU_OR ; cwen=`Y;end   
    `CSLLI     :begin cfu=`FU_ALU ; cop=`ALU_SLL; cwen=`Y;end
    `CSRAI     :begin cfu=`FU_ALU ; cop=`ALU_SRA; cwen=`Y;end
    `CSRLI     :begin cfu=`FU_ALU ; cop=`ALU_SRL; cwen=`Y;end
    `CSUB      :begin cfu=`FU_ALU ; cop=`ALU_SUB; cwen=`Y;end
    `CSUBW     :begin cfu=`FU_ALUW; cop=`ALU_SUB; cwen=`Y;end
    `CXOR      :begin cfu=`FU_ALU ; cop=`ALU_XOR; cwen=`Y;end
    `CJAL      :begin cfu=`FU_BRU ; cop=`BRU_CJAL ; cwen=`N;end

    `CLD       :begin cfu=`FU_LSU; cop=`LSU_RDX; cwen=`Y;end
    `CLDSP     :begin cfu=`FU_LSU; cop=`LSU_RDX; cwen=`Y;end
    `CLW       :begin cfu=`FU_LSU; cop=`LSU_RWS; cwen=`Y;end
    `CLWSP     :begin cfu=`FU_LSU; cop=`LSU_RWS; cwen=`Y;end
    `CSD       :begin cfu=`FU_LSU; cop=`LSU_WDX; cwen=`N;end
    `CSDSP     :begin cfu=`FU_LSU; cop=`LSU_WDX; cwen=`N;end
    `CSW       :begin cfu=`FU_LSU; cop=`LSU_WWX; cwen=`N;end
    `CSWSP     :begin cfu=`FU_LSU; cop=`LSU_WWX; cwen=`N;end
  
    `CEBREAK   :begin cfu=`FU_XXX; cop=`ALU_XXXX; cwen=`N;end
    default    :begin cfu=`FU_XXX; cop=`ALU_XXXX; cwen=`N;end
  endcase
end

// inst valid 
always@(*)begin
  casez(cinst)
  
    `CBEQZ     :begin needStop=`N;cValid = `Y;end
    `CBNEZ     :begin needStop=`N;cValid = `Y;end
    `CJ        :begin needStop=`N;cValid = `Y;end
    `CJR       :begin needStop=`N;cValid = (crs1 != 'd0);end
    `CJALR     :begin needStop=`N;cValid = (crs1 != 'd0);end

    `CADD      :begin needStop=`N; cValid = (crd != 'd0) && (crs2 != 'd0);end
    `CADDI     :begin needStop=`N; cValid = `Y;end
    `CADDI16SP :begin needStop=`N; cValid = |{cinst[12] , crs2};end
    `CADDI4SPN :begin needStop=`N; cValid = |cinst[12:5];end
    `CADDIW    :begin needStop=`N; cValid = (crd != 'd0);end
    `CADDW     :begin needStop=`N; cValid = `Y;end
    `CAND      :begin needStop=`N; cValid = `Y;end
    `CANDI     :begin needStop=`N; cValid = `Y;end
    `CLI       :begin needStop=`N; cValid = `Y;end
    `CLUI      :begin needStop=`N; cValid = (crd  != 'd2) && |{cinst[12],crs2};end  
    `CMV       :begin needStop=`N; cValid = (crs2 != 'd0);end
    `COR       :begin needStop=`N; cValid = `Y;end   
    `CSLLI     :begin needStop=`N; cValid = `Y;end
    `CSRAI     :begin needStop=`N; cValid = `Y;end
    `CSRLI     :begin needStop=`N; cValid = `Y;end
    `CSUB      :begin needStop=`N; cValid = `Y;end
    `CSUBW     :begin needStop=`N; cValid = `Y;end
    `CXOR      :begin needStop=`N; cValid = `Y;end
    `CJAL      :begin needStop=`N;cValid = `Y;end

    `CLD       :begin needStop=`N;cValid = `Y; end
    `CLDSP     :begin needStop=`N;cValid = (crd != 'd0); end
    `CLW       :begin needStop=`N;cValid = `Y; end
    `CLWSP     :begin needStop=`N;cValid = (crd != 'd0); end
    `CSD       :begin needStop=`N;cValid = `Y; end
    `CSDSP     :begin needStop=`N;cValid = `Y; end
    `CSW       :begin needStop=`N;cValid = `Y; end
    `CSWSP     :begin needStop=`N;cValid = `Y; end
  
    `CEBREAK   :begin needStop=`N;cValid = `Y;end
    default    :begin needStop=`N;cValid = `N;end
  endcase
end
// imm 
always@(*)begin
  casez(cinst)
    `CBEQZ     :begin cimm={{56{cinst[12]}},cinst[6:5],cinst[2],cinst[11:10],cinst[4:3],1'd0};end
    `CBNEZ     :begin cimm={{56{cinst[12]}},cinst[6:5],cinst[2],cinst[11:10],cinst[4:3],1'd0};end
    `CJ        :begin cimm={{53{cinst[12]}},cinst[8],cinst[10],cinst[9],cinst[6],cinst[7],cinst[2],cinst[11],cinst[5:3],1'b0};end
    `CJR       :begin cimm='d0;end
    `CJALR     :begin cimm='d0;end

    `CADD      :begin cimm='d0;end
    `CADDI     :begin cimm={{59{cinst[12]}},cinst[6:2]};end
    `CADDI16SP :begin cimm={{55{cinst[12]}},cinst[4],cinst[3],cinst[5],cinst[2],cinst[6],4'd0};end
    `CADDI4SPN :begin cimm={54'd0,cinst[10:7],cinst[12:11],cinst[5],cinst[6],2'd0};end
    `CADDIW    :begin cimm={{59{cinst[12]}},cinst[6:2]};end
    `CADDW     :begin cimm='d0;end
    `CAND      :begin cimm='d0;end
    `CANDI     :begin cimm={{59{cinst[12]}},cinst[6:2]};end
    `CLI       :begin cimm={{59{cinst[12]}},cinst[6:2]};end
    `CLUI      :begin cimm={{47{cinst[12]}},cinst[6:2],12'd0};end  
    `CMV       :begin cimm='d0;end
    `COR       :begin cimm='d0;end   
    `CSLLI     :begin cimm={58'd0,cinst[12],cinst[6:2]};;end
    `CSRAI     :begin cimm={58'd0,cinst[12],cinst[6:2]};;end
    `CSRLI     :begin cimm={58'd0,cinst[12],cinst[6:2]};;end
    `CSUB      :begin cimm='d0;end
    `CSUBW     :begin cimm='d0;end
    `CXOR      :begin cimm='d0;end
    `CJAL      :begin cimm={{53{cinst[12]}},cinst[8],cinst[10],cinst[9],cinst[6],cinst[7],cinst[2],cinst[11],cinst[5:3],1'b0};end

    `CLD       :begin cimm={56'd0,cinst[6:5],cinst[12:10],3'd0};end
    `CLDSP     :begin cimm={55'd0,cinst[4:2],cinst[12],cinst[6:5],3'd0};end
    `CLW       :begin cimm={57'd0,cinst[5],cinst[12:10],cinst[6],2'd0};end
    `CLWSP     :begin cimm={56'd0,cinst[3:2],cinst[12],cinst[6:4],2'd0};end
    `CSD       :begin cimm={56'd0,cinst[6:5],cinst[12:10],3'd0};end
    `CSDSP     :begin cimm={55'd0,cinst[9:7],cinst[12:10],3'd0};end
    `CSW       :begin cimm={57'd0,cinst[5],cinst[12:10],cinst[6],2'd0};end
    `CSWSP     :begin cimm={56'd0,cinst[8:7],cinst[12:9],2'd0};end
  
    `CEBREAK   :begin cimm='d0;end
    default    :begin cimm='d0;end
  endcase
end
// src1 src2 
always@(*)begin
  casez(cinst)
    `CBEQZ     :begin csrc1=`SRC_RF; csrc2=`SRC_RF;end
    `CBNEZ     :begin csrc1=`SRC_RF; csrc2=`SRC_RF;end
    `CJ        :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end
    `CJR       :begin csrc1=`SRC_RF; csrc2=`SRC_XX;end
    `CJALR     :begin csrc1=`SRC_RF; csrc2=`SRC_XX;end

    `CADD      :begin csrc1=`SRC_RF; csrc2=`SRC_RF;end
    `CADDI     :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end
    `CADDI16SP :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end
    `CADDI4SPN :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end
    `CADDIW    :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end
    `CADDW     :begin csrc1=`SRC_RF; csrc2=`SRC_RF;end
    `CAND      :begin csrc1=`SRC_RF; csrc2=`SRC_RF;end
    `CANDI     :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end
    `CLI       :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end
    `CLUI      :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end
    `CMV       :begin csrc1=`SRC_XX; csrc2=`SRC_RF;end
    `COR       :begin csrc1=`SRC_RF; csrc2=`SRC_RF;end
    `CSLLI     :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end
    `CSRAI     :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end
    `CSRLI     :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end
    `CSUB      :begin csrc1=`SRC_RF; csrc2=`SRC_RF;end
    `CSUBW     :begin csrc1=`SRC_RF; csrc2=`SRC_RF;end
    `CXOR      :begin csrc1=`SRC_RF; csrc2=`SRC_RF;end
    `CJAL      :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end

    `CLD       :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end
    `CLDSP     :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end
    `CLW       :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end
    `CLWSP     :begin csrc1=`SRC_RF; csrc2=`SRC_IM;end
    `CSD       :begin csrc1=`SRC_RF; csrc2=`SRC_RF;end
    `CSDSP     :begin csrc1=`SRC_RF; csrc2=`SRC_RF;end
    `CSW       :begin csrc1=`SRC_RF; csrc2=`SRC_RF;end
    `CSWSP     :begin csrc1=`SRC_RF; csrc2=`SRC_RF;end
  
    `CEBREAK   :begin csrc1=`SRC_XX; csrc2=`SRC_XX;end
    default    :begin csrc1=`SRC_XX; csrc2=`SRC_XX;end
  endcase
end
// rs1 rs2 rd
always@(*)begin
  casez(cinst)
    `CBEQZ     :begin crd='d0;crs1={2'd1,Crs1[2:0]};crs2='d0;end
    `CBNEZ     :begin crd='d0;crs1={2'd1,Crs1[2:0]};crs2='d0;end
    `CJ        :begin crd='d0;crs1='d0 ;crs2='d0;end
    `CJR       :begin crd='d0;crs1=Crs1;crs2='d0;end
    `CJALR     :begin crd='d1;crs1=Crs1;crs2='d0;end

    `CADD      :begin crd=Crd;crs1=Crd;crs2=Crs2;end
    `CADDI     :begin crd=Crd;crs1=Crd;crs2='d0 ;end
    `CADDI16SP :begin crd='d2;crs1='d2;crs2='d0 ;end
    `CADDI4SPN :begin crd={2'd1,Crs2[2:0]};crs1='d2;crs2='d0;end
    `CADDIW    :begin crd=Crd;crs1=Crd;crs2='d0 ;end
    `CADDW     :begin crd={2'd1,Crd[2:0]};crs1={2'd1,Crd[2:0]};crs2={2'd1,Crs2[2:0]};end
    `CAND      :begin crd={2'd1,Crd[2:0]};crs1={2'd1,Crd[2:0]};crs2={2'd1,Crs2[2:0]};end
    `CANDI     :begin crd={2'd1,Crd[2:0]};crs1={2'd1,Crd[2:0]};crs2='d0;end
    `CLI       :begin crd=Crd;crs1='d0;crs2='d0;end
    `CLUI      :begin crd=Crd;crs1='d0;crs2='d0;end
    `CMV       :begin crd=Crd;crs1='d0;crs2=Crs2;end
    `COR       :begin crd={2'd1,Crd[2:0]};crs1={2'd1,Crs1[2:0]};crs2={2'd1,Crs2[2:0]};end
    `CSLLI     :begin crd=Crd;crs1=Crd;crs2='d0;end
    `CSRAI     :begin crd={2'd1,Crd[2:0]};crs1={2'd1,Crd[2:0]};crs2='d0;end
    `CSRLI     :begin crd={2'd1,Crd[2:0]};crs1={2'd1,Crd[2:0]};crs2='d0;end
    `CSUB      :begin crd={2'd1,Crd[2:0]};crs1={2'd1,Crd[2:0]};crs2={2'd1,Crs2[2:0]};end
    `CSUBW     :begin crd={2'd1,Crd[2:0]};crs1={2'd1,Crd[2:0]};crs2={2'd1,Crs2[2:0]};end
    `CXOR      :begin crd={2'd1,Crd[2:0]};crs1={2'd1,Crd[2:0]};crs2={2'd1,Crs2[2:0]};end
    `CJAL      :begin crd='d1;crs1='d0 ;crs2='d0;end
    
    `CLD       :begin crd={2'd1,Crs2[2:0]};crs1={2'd1,Crs1[2:0]};crs2='d0;end
    `CLDSP     :begin crd=Crd;crs1='d2;crs2='d0;end
    `CLW       :begin crd={2'd1,Crs2[2:0]};crs1={2'd1,Crs1[2:0]};crs2='d0;end
    `CLWSP     :begin crd=Crd;crs1='d2;crs2='d0;end
    `CSD       :begin crd='d0;crs1={2'd1,Crs1[2:0]};crs2={2'd1,Crs2[2:0]};end
    `CSDSP     :begin crd='d0;crs1='d2;crs2=Crs2;end
    `CSW       :begin crd='d0;crs1={2'd1,Crs1[2:0]};crs2={2'd1,Crs2[2:0]};end
    `CSWSP     :begin crd='d0;crs1='d2;crs2=Crs2;end
  
    `CEBREAK   :begin crd='d0;crs1='d0;crs2='d0;end
    default    :begin crd='d0;crs1='d0;crs2='d0;end
  endcase
end

/* control signal generate */
assign {idu_isu_fu_o,
        idu_isu_op_o,
        idu_isu_src1_o,
        idu_isu_src2_o,
        idu_isu_rfwen_o} = outSel ? {cfu,cop,csrc1,csrc2,cwen}:decsignal[12:0];

assign idu_isu_rs1_o   = outSel ? crs1 : rs1;
assign idu_isu_rs2_o   = outSel ? crs2 : rs2;
assign idu_isu_rd_o    = outSel ? crd  : rd ;
assign idu_isu_imm_o   = outSel ? cimm : (
                         ({`XLEN{decsignal[15:13] == `IMM_I}} & imm_I) | 
                         ({`XLEN{decsignal[15:13] == `IMM_S}} & imm_S) | 
                         ({`XLEN{decsignal[15:13] == `IMM_B}} & imm_B) | 
                         ({`XLEN{decsignal[15:13] == `IMM_U}} & imm_U) | 
                         ({`XLEN{decsignal[15:13] == `IMM_J}} & imm_J) | 
                         ({`XLEN{decsignal[15:13] == `IMM_R}} & imm_R) |
                         ({`XLEN{decsignal[15:13] == `IMM_X}} & 'd0) );

assign idu_isu_pc_o      = iduPc   ;
assign idu_isu_inst_o    = curInst ;
assign idu_isu_predict_o = 'd0     ;
assign idu_ctrl_stall_o  = stall   ;
assign idu_isu_isCps_o   = outSel  ;

always@(posedge clk or negedge rst_n)
  if(~rst_n)
    iduPc <= boot_addr;
  else if(ctrl_idu_flush_i)
    iduPc <= redict_idu_pc_i;
  else if(idu_isu_hs)
    iduPc <= iduPc + (outSel ? 'd2 : 'd4);

// assert 
// always@(*)begin
//   if(~decsignal[16] & idu_isu_hs & ~outSel)begin
//     $display("Normal instr illegal %08x at addr %08x\n",inst , ibf_idu_vaddr_i);
//     $finish;
//   end
//   if(~cValid & idu_isu_hs & outSel)begin
//     $display("Compress instr illegal %04x at addr %08x\n",inst[15:0] , ibf_idu_vaddr_i);
//     $finish;
//   end
// end

`ifdef PRINT_IDU
always@(posedge clk)
  if (idu_isu_hs)begin
    $fwrite(32'h8000_0001, "{IDU} [PC : 0x%08x] -> %08x (Compress %1d)\n", iduPc,idu_isu_inst_o,outSel);//TODO 这里可以直连到regfile里
    $fflush();
  end
`endif

endmodule